import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import AgglomerativeClustering
from sklearn.neighbors import kneighbors_graph


# 定义一个实现凝聚层次聚类的函数
def perform_clustering(X,connectivity,title,num_clusters=3,linkage='ward'):
    plt.figure()
    model = AgglomerativeClustering(linkage=linkage,connectivity=connectivity,n_clusters=num_clusters)
    model.fit(X)
    # 提取标签,然后指定图形中使用的标记形式
    # 提取标签
    labels = model.labels_
    # 为不同的簇设定不同的标记样式
    markers = '.vx'
    # 迭代数据
    for i,marker in zip(range(num_clusters),markers):
        # 画出属于当前点的簇
        plt.scatter(X[labels==i,0],X[labels==i,1],s=50,marker=marker,color='k',facecolors='none')
        plt.title(title)
        plt.show()

def add_noise(x,y,amplitude):
    X = np.concatenate((x,y))
    X+= amplitude*np.random.randn(2,X.shape[1])
    return X.T


def get_spiral(t,noise_amplitude=0.5):
    r = t
    x= r*np.cos(t)
    y = r*np.sin(t)

    return add_noise(x,y,noise_amplitude)


def get_rose(t,noise_amplitude=0.02):
    k = 5
    r = np.cos(k*t)+0.25
    x = r*np.cos(t)
    y = r*np.sin(t)

    return add_noise(x,y,noise_amplitude)


if __name__ == '__main__':
    # 生成样本数据
    n_samples = 500
    np.random.seed(2)
    t = 2.5 *np.pi*(1+2*np.random.rand(1,n_samples))
    X = get_spiral(t)

    # 不使用连接性
    connectivity = None
    perform_clustering(X,connectivity,'No connectivity')

    # 创建k近邻图
    connectivity = kneighbors_graph(X,10,include_self=True)
    perform_clustering(X,connectivity,'K-Neighbors connectivity')